import React, { createContext, ReactElement } from 'react';
import { flatten, groupWith, last, map, pipe } from 'ramda';

import moment from 'moment';
import { State, Action, Context } from './types';
import actions from './actions';
import Provider from '../../../../components/Provider';
import { setLastMessageId } from './store/messageId';
import { Message } from '../../../../api/class/getMessageList';
import { canWithDraw } from './util';
import { MessageType } from './constant';
import { getUserInfo } from '../../../../store/user';

export const initialState: State = {
  showRecord: false,
  isVod: false,
  messageList: [],
  vodMessageList: [],
  bubbleMessageList: [],
  unReadNumber: 0,
  lessonId: 0,
  assistantInfo: {
    id: 0,
    headUrl: '',
    name: ''
  },
  dateList: [],
  lessonStartTime: ''
};

export const reducer = (state: State, action: Action): State => {
  switch (action.type) {
    case 'SET_SHOW_RECORD': {
      const { messageList, lessonId } = state;
      const lastMessage = last(messageList);
      if (lastMessage && action.value) {
        const { userId } = getUserInfo();
        setLastMessageId(lastMessage.messageId, lessonId, Number(userId));
      }
      return {
        ...state,
        showRecord: action.value,
        unReadNumber: 0,
        bubbleMessageList: []
      };
    }
    case 'SET_MESSAGE_LIST': {
      const { showRecord, isVod, lessonId } = state;
      const messageList = action.value.map(
        (message): Message => ({
          ...message,
          canWithDraw: !isVod && canWithDraw(message.sendTime)
        })
      );
      const lastMessage = last(messageList);
      if (lastMessage && showRecord) {
        const { userId } = getUserInfo();
        setLastMessageId(lastMessage.messageId, lessonId, Number(userId));
      }
      let firstSendTime = '';
      const validMessageList = messageList.filter(
        (message): boolean =>
          message.type === MessageType.Text ||
          message.type === MessageType.Voice
      );
      if (validMessageList.length > 0) {
        firstSendTime = validMessageList[0].sendTime;
      }
      const dateList = pipe(
        groupWith(
          (a: Message, b: Message): boolean =>
            Math.floor(
              (moment(a.sendTime).unix() - moment(firstSendTime).unix()) / 300
            ) ===
            Math.floor(
              (moment(b.sendTime).unix() - moment(firstSendTime).unix()) / 300
            )
        ),
        map((messages: Message[]): Message => messages[0]),
        flatten,
        map((message: Message): string => message.sendTime)
      )(validMessageList);
      return { ...state, messageList, dateList };
    }
    case 'SET_VOD_MESSAGE_LIST': {
      return { ...state, vodMessageList: action.value };
    }
    case 'SET_BUBBLE_MESSAGE_LIST':
      return { ...state, bubbleMessageList: action.value };
    case 'SET_UN_READ_NUMBER':
      return { ...state, unReadNumber: action.value };
    case 'INIT_CHAT_ROOM_PROPS': {
      const { lessonId, assistantInfo, isVod, lessonStartTime } = action.value;
      return { ...state, lessonId, assistantInfo, isVod, lessonStartTime };
    }
    default:
      return state;
  }
};

export const Store = createContext<Context>({
  state: initialState
});

export default (props: { [key: string]: any }): ReactElement => {
  return (
    <Provider
      reducer={reducer}
      initialState={initialState}
      Store={Store}
      actions={actions}
      {...props}
    />
  );
};
